using UnityEngine;
using UnityEngine.Tilemaps;

public class Board : MonoBehaviour
{
    public TetrominoData[] tetrominoDatas = new TetrominoData[7];
    public Piece activePiece{get;private set;}
    public Vector3Int position;
    public Tilemap tilemap{get;private set;}
    public Vector2Int boardSize =  new Vector2Int(12,22);
    public RectInt Bounds
    {
        get
        {
            Vector2Int originalPosition = new Vector2Int(-boardSize.x/2,-boardSize.y/2);
            return new RectInt(originalPosition,boardSize);
        }
    }
    public event System.Action<int> onLinesCleared;
    public event System.Action onGameOver;
    public bool gameOver{get;private set;}
    public void Awake()
    {
        activePiece = GetComponent<Piece>();
        tilemap = GetComponentInChildren<Tilemap>();
        for(int i = 0;i<tetrominoDatas.Length;i++)
        {
            tetrominoDatas[i].Initial();
        }
        gameOver = false;
    }
    public void Start()
    {
        GeneratePiece();
    }
    public void GeneratePiece()
    {
        int random = Random.Range(0,tetrominoDatas.Length);
        TetrominoData data = tetrominoDatas[random];
        activePiece.Initialize(this,position,data);
        Debug.Log($"方块{tetrominoDatas[random].type}");
        if(!IsValidPostion (activePiece,position))
        {
            gameOver  = true;
            Debug.Log("游戏结束");
            onGameOver?.Invoke();
        }
        if(gameOver)
        {
            Debug.Log("不在产生方块");
            return;
        }
        SetPiece(activePiece);
    }
    public void RestartGame()
    {
        Debug.Log("重启游戏");
        //清除游戏板的方块
        ClearBoard();
        //产生方块
        GeneratePiece();
    }
    public void ClearBoard()
    {
        RectInt bounds = this.Bounds;
        for(int row = bounds.yMin;row<bounds.yMax;row++)
        {
            for(int col = bounds.xMin;col<bounds.xMax;col++)
            {
                Vector3Int position = new Vector3Int(col,row,0);
                tilemap.SetTile(position,null);
            }
        }
        gameOver = false;
    }
    public void SetPiece(Piece piece)
    {
        for(int i = 0;i<piece.cells.Length;i++)
        {
            Vector3Int tilePosition = piece.cells[i]+piece.position;
            tilemap.SetTile(tilePosition,piece.data.tile);
        }
    }
        public void ClearPiece(Piece piece)
    {
        for(int i = 0;i<piece.cells.Length;i++)
        {
            Vector3Int tilePosition = piece.cells[i]+piece.position;
            tilemap.SetTile(tilePosition,null);
        }
    }
    public bool IsValidPostion(Piece piece, Vector3Int position)
    {
        RectInt bounds = this.Bounds;
        for(int i = 0;i<piece.cells.Length;i++)
        {
            Vector3Int tilePosition = piece.cells[i]+position;
            if(!bounds.Contains((Vector2Int)tilePosition))
            {
                Debug.Log("超出边界");
                return false;
            }
            if(tilemap.HasTile(tilePosition))
            {
                Debug.Log("被占用");
                return false;
            }
        }
        return true;
    }
    public void LockPiece(Piece piece)
    {
        SetPiece(piece);
        //消除行
        ClearLines();
        GeneratePiece();
    }
    private void ClearLines()
    {
        RectInt bounds = this.Bounds;
        int row  = bounds.yMin;
        int rowsCleared = 0;
        while(row<bounds.yMax)
        {
            if(IsLineFull(row))
            {
                rowsCleared++;
                ClearRow(row);
                //上面行自动下落
                DropRow(row+1);
            }
            else
            {
                row++;
            }
        }
        if(rowsCleared>0)
        {
            onLinesCleared?.Invoke(rowsCleared);
        }
    }
    private bool IsLineFull(int row)
    {
        RectInt bounds = this.Bounds;
        for(int col = bounds.xMin;col<bounds.xMax;col++)
        {
            Vector3Int position = new Vector3Int(col,row,0);
            if(!tilemap.HasTile(position))
            {
                return false;
            }
        }
        return true;
    }
    private void ClearRow(int row)
    {
        RectInt bounds = this.Bounds;
        for(int col = bounds.xMin;col<bounds.xMax;col++)
        {
            Vector3Int position = new Vector3Int(col,row,0);
            tilemap.SetTile(position,null);
        }
    }
    private void DropRow(int startRow)
    {
        RectInt bounds = this.Bounds;
        for(int row = startRow;row<bounds.yMax;row++)
        {
            for(int col = bounds.xMin;col<bounds.xMax;col++)
            {
                Vector3Int above = new Vector3Int(col,row,0);
                Vector3Int below = new Vector3Int(col,row-1,0);
                TileBase tile = tilemap.GetTile(above);
                tilemap.SetTile(below,tile);
                tilemap.SetTile(above,null);
            }
        }
    }
}
